/************************************************************************
*    File Name:  rt771_6b_packer.v
*     Revision:  V1.0
* Release Date:  2015/06/18
*        Model:
* Dependencies:
*  Description:  (For 1H503)
*                iSP  Packer 6 bits to 8 bits (rdclk: 14T, rdfclk: 8T clock latency)
*
*      Company:  AUO
*     Engineer:  Jie Ho
*  Create Date:  2015/06/16
*
* Rev  Author        Date        Changes
* ---  ------------  ----------  ---------------------------------------
* 1.0  Jie Ho        2015/06/18  Initial release
************************************************************************/

`timescale 1ns/10ps

module rt771_6b_packer(
// Input 
reset_n,
dclk,

isp_en,
port_num,
opbit,
final_pasel,

in_r,
in_g,
in_b,
in_srart,
in_cycle_cnt,
in_port_define,


// Output
o_fifo_din,
o_fifo_wen,
o_fifo_waddr,
o_fifo_ren,
o_fifo_raddr

);


// Input 
input       reset_n;        
input       dclk;   

input       isp_en;
input [2:0] port_num;     
input [1:0] opbit;
input       final_pasel;

input [9:0] in_r;
input [9:0] in_g;
input [9:0] in_b;
input       in_srart;
input [2:0] in_cycle_cnt;
input [4:0] in_port_define;   //port0~port15


// Output
output [29:0] o_fifo_din;
output        o_fifo_wen;
output        o_fifo_ren;
output [4:0]  o_fifo_waddr;
output [4:0]  o_fifo_raddr;







///////////////////////////////////////////////
//                                           //
//              flag process                 //
//                                           //
///////////////////////////////////////////////

//port number settihg flag
wire port_num_4 = (port_num == 3'd0) ? 1'd1 : 1'd0;      
wire port_num_6 = (port_num == 3'd1) ? 1'd1 : 1'd0;
wire port_num_8 = (port_num == 3'd2) ? 1'd1 : 1'd0;
wire port_num_12 = (port_num == 3'd3) ? 1'd1 : 1'd0;
wire port_num_16 = (port_num == 3'd4) ? 1'd1 : 1'd0;

wire port_num_4n = port_num_4 | port_num_8 | port_num_12 | port_num_16;



//packer number setting flag
wire port_1 = (in_port_define == 5'd1) ? 1'd1 : 1'd0;
wire port_2 = (in_port_define == 5'd2) ? 1'd1 : 1'd0;
wire port_3 = (in_port_define == 5'd3) ? 1'd1 : 1'd0;
wire port_4 = (in_port_define == 5'd4) ? 1'd1 : 1'd0;
wire port_5 = (in_port_define == 5'd5) ? 1'd1 : 1'd0;
wire port_6 = (in_port_define == 5'd6) ? 1'd1 : 1'd0;
wire port_7 = (in_port_define == 5'd7) ? 1'd1 : 1'd0;
wire port_8 = (in_port_define == 5'd8) ? 1'd1 : 1'd0;
wire port_9 = (in_port_define == 5'd9) ? 1'd1 : 1'd0;
wire port_10 = (in_port_define == 5'd10) ? 1'd1 : 1'd0;
wire port_11 = (in_port_define == 5'd11) ? 1'd1 : 1'd0;
wire port_12 = (in_port_define == 5'd12) ? 1'd1 : 1'd0;
wire port_13 = (in_port_define == 5'd13) ? 1'd1 : 1'd0;
wire port_14 = (in_port_define == 5'd14) ? 1'd1 : 1'd0;
wire port_15 = (in_port_define == 5'd15) ? 1'd1 : 1'd0;
wire port_16 = (in_port_define == 5'd16) ? 1'd1 : 1'd0;

wire port_1256 = port_1 | port_2 | port_5 | port_6;
wire port34 = port_3 | port_4;










///////////////////////////////////////////////
//                                           //
//            shift reg write in             //
//                                           //
///////////////////////////////////////////////

// for wr_cycle_cnt add flag
wire cycle_0 = (in_cycle_cnt == 3'd0) ? 1'd1: 1'd0;
wire cycle_1 = (in_cycle_cnt == 3'd1) ? 1'd1: 1'd0;
wire cycle_2 = (in_cycle_cnt == 3'd2) ? 1'd1: 1'd0;
wire cycle_3 = (in_cycle_cnt == 3'd3) ? 1'd1: 1'd0;
wire cycle_4 = (in_cycle_cnt == 3'd4) ? 1'd1: 1'd0;
wire cycle_5 = (in_cycle_cnt == 3'd5) ? 1'd1: 1'd0;




reg [2:0] wr_cycle_cnt_6p_1256;  
begin
 if (!reset_n)
 wr_cycle_cnt_6p_1256 <= 3'd0;
 else begin
   if (in_srart)
   wr_cycle_cnt_6p_1256 <= 3'd0;
   else if (port_num_6 & (cycle_0 | cycle_2 | cycle_3 | cycle_5))
        wr_cycle_cnt_6p_1256 <= wr_cycle_cnt_6p_1256 + 3'd1;
		else
		wr_cycle_cnt_6p_1256 <= wr_cycle_cnt_6p_1256; 
 end
end



reg [2:0] wr_cycle_cnt_6p_34;  
begin
 if (!reset_n)
 wr_cycle_cnt_6p_34 <= 3'd0;
 else begin
   if (in_srart)
   wr_cycle_cnt_6p_34 <= 3'd0;
   else if (port_num_6 & (cycle_1 | cycle_2 | cycle_4 | cycle_5))
        wr_cycle_cnt_6p_34 <= wr_cycle_cnt_6p_34 + 3'd1;
		else
		wr_cycle_cnt_6p_34 <= wr_cycle_cnt_6p_34;
 end
end



reg [2:0] wr_cycle_cnt_4n;  
begin
 if (!reset_n)
 wr_cycle_cnt <= 3'd0;
 else begin
   if (in_srart)
   wr_cycle_cnt_4n <= 3'd0;
   else if (port_num_4n & cycle_3)
   wr_cycle_cnt_4n <= wr_cycle_cnt_4n + 3'd1;
        else
		wr_cycle_cnt_4n <= wr_cycle_cnt_4n; 
 end
end


wire [2:0] wr_cycle_cnt = (port_num_6 & port_1256) ? wr_cycle_cnt_6p_1256 : ((port_num_6 & port_34) ? wr_cycle_cnt_6p_34 : wr_cycle_cnt_4n);




















///////////////////////////////////////////////
//                                           //
//          packer cnt Pre-process           //
//                                           //
///////////////////////////////////////////////

//packer counter start
reg in_srart_d1, in_srart_d2;
wire in_srart_extend = in_srart | in_srart_d1 | in_srart_d2;  //for 6port case

always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 begin
  in_srart_d1 <= 1'd0; 
  in_srart_d2 <= 1'd0; 
 end else begin
     in_srart_d1 <= in_srart; 
     in_srart_d2 <= in_srart_d1; 
     end
end



reg [1:0] cycle_2_cnt;                                    //for 4n_port pack_cnt_start flag       
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
 cycle_2_cnt <= 2'd0;
 else begin
  if (in_srart)
  cycle_2_cnt <= 2'd0;
  else if (cycle_2_cnt == 2'd3)
       cycle_2_cnt <= 2'd3
       else if (in_cycle_cnt == 3'd2)
            cycle_2_cnt <= cycle_2_cnt + 2'd1;
			else
			cycle_2_cnt <= cycle_2_cnt;
 end
end

reg pack_cnt_start;
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_start <= 1'd0;
 else begin 
  if (port_num_6)
  pack_cnt_start <= (in_cycle_cnt == 3'd1) & in_srart_extend;
  else if (cycle_2_cnt == 2'd2)
       pack_cnt_start <= 1'd1;
	   else
	   pack_cnt_start <= 1'd0; 
 end
end
























///////////////////////////////////////////////
//                                           //
//             package counter               //
//                                           //
///////////////////////////////////////////////

reg [3:0] pack_cnt_temp;              //only for 6port case
reg [3:0] pack_cnt_temp_end;

always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_temp <= 4'd0;
 else begin 
   if (port_num_4n)
   pack_cnt_temp <= 4'd0;
   else if (pack_cnt_start)
        pack_cnt_temp <= 4'd0;
        else if (pack_cnt_temp == pack_cnt_temp_end)
		     pack_cnt_temp <= 4'd0;
			 else
			 pack_cnt_temp <= pack_cnt_temp + 4'd1;
 end
end


always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_temp_end <= 4'd0;
 else begin
   if (port_num_4n)
   pack_cnt_temp_end <= 4'd0;
   else if (port_num_6)
        pack_cnt_temp_end <= 4'd11;
		else
		pack_cnt_temp_end <= 4'd0; 
  end
 end

 
 
// fpr 6port 6bit packer add flag
wire pack_cnt_temp_0 = (pack_cnt_temp == 4'd0) ? 1'd1: 1'd0;
wire pack_cnt_temp_1 = (pack_cnt_temp == 4'd1) ? 1'd1: 1'd0;
wire pack_cnt_temp_2 = (pack_cnt_temp == 4'd2) ? 1'd1: 1'd0;
wire pack_cnt_temp_3 = (pack_cnt_temp == 4'd3) ? 1'd1: 1'd0;
wire pack_cnt_temp_4 = (pack_cnt_temp == 4'd4) ? 1'd1: 1'd0;
wire pack_cnt_temp_5 = (pack_cnt_temp == 4'd5) ? 1'd1: 1'd0;
wire pack_cnt_temp_6 = (pack_cnt_temp == 4'd6) ? 1'd1: 1'd0;
wire pack_cnt_temp_7 = (pack_cnt_temp == 4'd7) ? 1'd1: 1'd0;
wire pack_cnt_temp_8 = (pack_cnt_temp == 4'd8) ? 1'd1: 1'd0;
wire pack_cnt_temp_9 = (pack_cnt_temp == 4'd9) ? 1'd1: 1'd0;
wire pack_cnt_temp_10 = (pack_cnt_temp == 4'd10) ? 1'd1: 1'd0;
wire pack_cnt_temp_11 = (pack_cnt_temp == 4'd11) ? 1'd1: 1'd0;

wire pack_cnt_add_1256 = pack_cnt_temp_0 | pack_cnt_temp_3 | pack_cnt_temp_5 | pack_cnt_temp_6 | pack_cnt_temp_8 | pack_cnt_temp_11;
wire pack_cnt_add_34   = pack_cnt_temp_1 | pack_cnt_temp_4 | pack_cnt_temp_5 | pack_cnt_temp_7 | pack_cnt_temp_8 | pack_cnt_temp_11;
 
 
 
 
 
 
// 6port 6bit packer counter 
reg [2:0] pack_cnt_6p;                       
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_6p <= 3'd0;
 else begin
   if (port_num_4n)
   pack_cnt_6p <= 3'd0;
   else if (pack_cnt_start)
        pack_cnt_6p <= 3'd0;
		else if (pack_cnt_6p == 3'd5)
		     pack_cnt_6p <= 3'd0;
             else if (port_1256 & pack_cnt_add_1256)
                  pack_cnt_6p <= pack_cnt_6p + 3'd1;
	           	  else if (port_34 & pack_cnt_add_34)
                       pack_cnt_6p <= pack_cnt_6p + 3'd1;
	           	       else 
	           	       pack_cnt_6p <= pack_cnt_6p;
  end
end 
 
 

 
// 4n port 6bit packer counter 
reg [2:0] pack_cnt_4n; 
always @(posedge dclk or negedge reset_n)
begin
 if (!reset_n)
  pack_cnt_4n <= 3'd0;
 else begin
   if (port_num_6)
   pack_cnt_4n <= 3'd0;
   else if (pack_cnt_start)
        pack_cnt_4n <= 3'd0;
		else if (pack_cnt_4n == 3'd7)
		     pack_cnt_4n <= 3'd0;
			 else if (in_cycle_cnt == 3'd3)
			 pack_cnt_4n <= pack_cnt_4n + 3'd1;
			      else
				  pack_cnt_4n <= pack_cnt_4n; 
 end
end 
 
 
 
 






















 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


endmodule




























